using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Threading;

namespace net.notdot.Attercop.Client
{
    public class TaskCompletedEventArgs : EventArgs
    {
        public ITask Task;

        public TaskCompletedEventArgs(ITask task)
        {
            this.Task = task;
        }
    }

    public class TaskThread : ITaskThread
    {
        protected Thread workerThread = null;
        protected Queue<ITask> handlerQueue = new Queue<ITask>();
        protected ITask current;
        protected double totalSize = 0;
        protected double completedSize = 0;

        public EventHandler<TaskCompletedEventArgs> OnTaskCompleted;
        public EventHandler OnStarted;
        public EventHandler OnCompleted;

        public TaskThread()
        {
        }

        #region ITaskThread Members

        public void AddTask(ITask task)
        {
            lock (handlerQueue)
            {
                handlerQueue.Enqueue(task);
                totalSize += task.TaskSize;
                if (workerThread == null || !workerThread.IsAlive)
                    Start();
            }
        }

        public TimeSpan EstimateTimeRemaining()
        {
            throw new Exception("The method or operation is not implemented.");
        }

        public double TaskSize
        {
            get
            {
                return totalSize;
            }
        }

        public double TaskComplete
        {
            get {
                return completedSize + ((current != null)?current.TaskComplete:0);
            }
        }

        public bool IsRunning
        {
            get
            {
                return workerThread != null && workerThread.IsAlive;
            }
        }

        public void Start()
        {
            lock (handlerQueue)
            {
                if (workerThread != null && workerThread.IsAlive)
                    return;

                workerThread = new Thread(new ThreadStart(WorkerThreadMain));
                workerThread.IsBackground = true;
                workerThread.Start();
            }
        }

        public void Stop()
        {
            lock (handlerQueue)
            {
                if (workerThread == null)
                    return;

                workerThread.Abort();
                workerThread = null;
                current = null;
            }
        }
#endregion

        protected void WorkerThreadMain()
        {
            if (OnStarted != null)
                OnStarted(this, new EventArgs());

            lock (handlerQueue)
            {
                if (handlerQueue.Count == 0)
                {
                    current = null;
                }
                else
                {
                    current = handlerQueue.Peek();
                }
            }

            while (current != null)
            {
                //Execute the task
                current.DoTask();
                completedSize += current.TaskSize;

                if(OnTaskCompleted != null)
                    OnTaskCompleted(this, new TaskCompletedEventArgs(current));

                //Get the next task
                lock (handlerQueue)
                {
                    handlerQueue.Dequeue();

                    if (handlerQueue.Count == 0)
                    {
                        current = null;
                    }
                    else
                    {
                        current = handlerQueue.Peek();
                    }
                }
            }

            if (OnCompleted != null)
                OnCompleted(this, new EventArgs());
        }
    
    }
}
